#ifndef MSLOG_INNER_H
#define MSLOG_INNER_H

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include<pthread.h> 
#include "mstype.h"
/*----------------------------------------------*
 * enum											*
 *----------------------------------------------*/
typedef enum {
	mslog_level_assert=0x00,
   	mslog_level_error,
   	mslog_level_warn,
   	mslog_level_info,
   	mslog_level_debug,
   	mslog_level_verbose,
   	mslog_level_more,
   	mslog_level_max
}ENLOGLevel;

#if defined(OS_LINUX_SOC)

#define mscolor_black	"30"
#define mscolor_red		"31"
#define mscolor_green	"32"
#define mscolor_brown	"33"
#define mscolor_blue	"34"
#define mscolor_purple	"35"
#define mscolor_cyan	"36"
#define mscolor_gray	"37"

#define mscolor_nor(color)	"\e[0;"color"m"
#define mscolor_bold(color)	"\e[1;"color"m"
#define mscolor_reset		"\e[0m"

#define UNDERLINE	"\e[4m"
#define REVERSE		"\e[7m"
//打印级别颜色设置
static const ms_string ms_col[64]={
	mscolor_nor(mscolor_red),	//assert
	mscolor_bold(mscolor_red),	//error
	mscolor_nor(mscolor_brown),	//waring
	mscolor_bold(mscolor_blue),	//info
	mscolor_reset,				//debug
	mscolor_nor(mscolor_green),	//verbose
	mscolor_nor(mscolor_cyan)};	//more
#else
#define mscolor_reset   ""           
static const ms_string ms_col[64]={
	"",		//assert
	"",		//error
	"",		//waring
	"",		//info
	"",		//debug
	"",		//verbose
	""};	//more
#endif

/*----------------------------------------------*
 * macros                              			*
 *----------------------------------------------*/
#define DEFAULT_LOG_LEVEL  		(mslog_level_max-1)

#if 0
#define LINE_FMT		"[%s %s %d]"
#define LINE_ARG		__FILE__,__FUNCTION__, __LINE__
#else
#define LINE_FMT		"[%s %d]"
#define LINE_ARG		__FUNCTION__, __LINE__
#endif
#define LINE_END "\r\n"
#define LOGLEVE_FMT	"[%s]"
#define PRINT printf

//文件日志、级别颜色、日志时间、日志级别、日志FLAG、支持打印FLAG过滤、打印所在行和函数名打印、自动加换行符
#define LOG_DBG( level, flag , fmt, arg...)\
	\
	if ( !(level >  mslog_api_getLoglevel()) ){\
		if(strlen(strfilterTags)==0 ||0!=mslog_api_strCasestrNum(strfilterTags,flag,ms_true,ms_true)){ \
			if(flag_printLineFunc) { \
				mslog_innerapi_file("%s"LOGLEVE_FMT"[%s]" LINE_FMT fmt LINE_END, \
					mslog_innerapi_logTime(),strLoglevel_simple[level],flag,LINE_ARG,##arg);\
				if(flag_stdPrint) {PRINT("%s %s"LOGLEVE_FMT"[%s]" LINE_FMT fmt mscolor_reset LINE_END, \
					ms_col[level],mslog_innerapi_logTime(),strLoglevel_simple[level],flag,LINE_ARG,##arg );}\
			}else{\
				mslog_innerapi_file("%s"LOGLEVE_FMT"[%s]" fmt LINE_END, \
					mslog_innerapi_logTime(),strLoglevel_simple[level],flag,##arg); \
				if(flag_stdPrint) {PRINT("%s %s"LOGLEVE_FMT"[%s]" fmt mscolor_reset LINE_END, \
					ms_col[level],mslog_innerapi_logTime(),strLoglevel_simple[level],flag,##arg );} \
			} \
		} \
	}
//文件日志、级别颜色、日志时间、日志级别、日志FLAG、支持打印FLAG过滤
#define LOG_DBG1( level, flag , fmt, arg...)\
	if ( !(level >  mslog_api_getLoglevel()) ){\
		if(strlen(strfilterTags)==0 ||0!=mslog_api_strCasestrNum(strfilterTags,flag,ms_true,ms_true)){ \
			mslog_innerapi_file("%s"LOGLEVE_FMT"[%s]" fmt , \
				mslog_innerapi_logTime(),strLoglevel_simple[level],flag,##arg);\
			if(flag_stdPrint) PRINT("%s %s"LOGLEVE_FMT"[%s]" fmt mscolor_reset , \
				ms_col[level], mslog_innerapi_logTime(),strLoglevel_simple[level],flag,##arg );\
		} \
	}
	
//文件日志、级别颜色
#define LOG_DBG2( level , fmt, arg...)\
	if ( !(level >  mslog_api_getLoglevel()) ){\
		mslog_innerapi_file(fmt ,##arg);\
		if(flag_stdPrint) PRINT(  "%s"fmt mscolor_reset ,ms_col[level], ##arg );\
	}
//级别颜色、自动加换行符
#define LOG_DBG3( level , fmt, arg...)\
	if ( !(level >mslog_api_getLoglevel()) ){\
		if(flag_stdPrint) PRINT(  "%s"fmt mscolor_reset LINE_END,ms_col[level], ##arg );\
	}

#define bufcheck_noret(dbuf) \
	if(NULL==dbuf){ \
		return; \
	}

#define bufcheck(dbuf) \
	if(NULL==dbuf){ \
		ms_errNoret("dbuf is null"); \
	}
#define bufcheck_ret(ret,dbuf) \
	if(NULL==dbuf){ \
		ms_errRet(ret,"dbuf is null"); \
	}
#define bufcheck_goto(gval,dbuf) \
	if(NULL==dbuf){ \
		ms_error("dbuf  is null"); \
		goto gval; \
	}

#define bufcheck_des(buf,fmt,arg...) \
	if(NULL==buf){ \
		ms_errNoret(fmt,##arg); \
	}
	
#define bufcheckret_des(ret,buf,fmt,arg...) \
	if(NULL==buf){ \
		ms_errRet(ret,fmt,##arg); \
	}
	
#define bufcheck_goto_des(gval,buf,fmt,arg...) \
	if(NULL==buf){ \
		ms_error(fmt,##arg); \
		goto gval; \
	}
#define mslog_api_toFile(filename,msg,fmt, arg...) 	\
	if(NULL!=msg){ \
		memset(msg,0,sizeof(msg));\
		if(sizeof(msg)>8){ \
			snprintf(msg,sizeof(msg),fmt,##arg); \
		}else{ \
			sprintf(msg,fmt,##arg); \
		} \
	} \
	mslog_innerapi_write(filename,"%s " fmt LINE_END, mslog_innerapi_logTime(),##arg);
/*****************************************************************************
 Description  : mslog with use-flags api
*****************************************************************************/
#define ms_lfatal(flag , fmt, arg...) 		LOG_DBG( mslog_level_assert	, flag , fmt, ##arg)
#define ms_lerror(flag , fmt, arg...) 		LOG_DBG( mslog_level_error	, flag , fmt, ##arg)
#define ms_lwaring(flag , fmt, arg...) 		LOG_DBG( mslog_level_warn	, flag , fmt, ##arg)
#define ms_linfo(flag , fmt, arg...) 		LOG_DBG( mslog_level_info	, flag , fmt, ##arg)
#define ms_ldebug(flag , fmt, arg...) 		LOG_DBG( mslog_level_debug	, flag , fmt, ##arg)
#define ms_lverbose(flag , fmt, arg...) 	LOG_DBG( mslog_level_verbose   , flag , fmt, ##arg)
#define ms_lmore(flag , fmt, arg...) 		LOG_DBG( mslog_level_more	, flag , fmt, ##arg)

#define ms_lfatal1(flag , fmt, arg...) 		LOG_DBG1( mslog_level_assert   ,flag , fmt, ##arg)
#define ms_lerror1(flag , fmt, arg...) 		LOG_DBG1( mslog_level_error	,flag , fmt, ##arg)
#define ms_lwaring1(flag , fmt, arg...) 	LOG_DBG1( mslog_level_warn	,flag , fmt, ##arg)
#define ms_linfo1(flag , fmt, arg...) 		LOG_DBG1( mslog_level_info	,flag , fmt, ##arg)
#define ms_ldebug1(flag , fmt, arg...) 		LOG_DBG1( mslog_level_debug	,flag , fmt, ##arg)
#define ms_lverbose1(flag , fmt, arg...) 	LOG_DBG1( mslog_level_verbose ,flag , fmt, ##arg)
#define ms_lmore1(flag , fmt, arg...) 		LOG_DBG1( mslog_level_more	,flag , fmt, ##arg)
/*****************************************************************************

*****************************************************************************/
#ifndef MSLOG_C 
#define INTERFACE_LOG extern
#else
#define INTERFACE_LOG 
#endif

INTERFACE_LOG ms_bool flag_stdPrint;
INTERFACE_LOG ms_bool flag_printLineFunc;
INTERFACE_LOG ms_array strfilterTags[4096];
INTERFACE_LOG const ms_string strLoglevel_simple[32];

INTERFACE_LOG ms_void 
	mslog_innerapi_file(const char *format,...);
INTERFACE_LOG ms_string 
	mslog_innerapi_logTime(ms_void);
INTERFACE_LOG ms_void    
	mslog_innerapi_bufHex( ms_string ms_in description,ms_pu08 ms_in buf, ms_u32 ms_in len,ms_cstring ms_in func,ms_u32 ms_in line);
INTERFACE_LOG ms_void    
	mslog_innerapi_bufHexAscii( ms_string ms_in description,ms_pu08 ms_in buf, ms_u32 ms_in len,ms_cstring ms_in func,ms_u32 ms_in line);
INTERFACE_LOG ms_void    
	mslog_innerapi_bufHexErr( ms_string ms_in description,ms_pu08 ms_in buf, ms_u32 ms_in len,ms_cstring ms_in func,ms_u32 ms_in line);
INTERFACE_LOG ms_void   
	mslog_innerapi_bufAscii( ms_string ms_in description,ms_pu08 ms_in buf, ms_u32 ms_in len,ms_cstring ms_in func,ms_u32 ms_in line);
INTERFACE_LOG ms_s32 
	mslog_innerapi_write(ms_string ms_in filename,const char *format,...);
INTERFACE_LOG ms_string 
	mslog_innerapi_num2str( ms_string ms_out outstr, ms_s64 ms_in num);
INTERFACE_LOG ms_string 
	mslog_innerapi_bitByte64( ms_string ms_out outstr, ms_u64 ms_in num64_h, ms_u64 ms_in num64_l,ms_string punit);
INTERFACE_LOG ms_string 
	mslog_innerapi_bitByte32( ms_string ms_out outstr, ms_u32 ms_in num32_h, ms_u32 ms_in num32_l,ms_string punit);
INTERFACE_LOG ms_void 
	mslog_api_color(ms_void);

#endif

